//#include <NTDDK.h>
#include <ifs/wnet/ntifs.h>
//#include <wdm.h>

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverEntry (
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath);

#pragma alloc_text(init, DriverEntry)
#pragma alloc_text(page, DriverUnload)

static NTSTATUS ignore(IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp)
{
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);

	KdPrint(("%s type = %d, UserBuffer = %p\n", __FUNCTION__, Irp->Type, Irp->UserBuffer));		
	KdPrint(("%s[%d][%d] control[%d] DeviceObject = %p, FileObject = %p\n", __FUNCTION__,
			pIrpStack->MajorFunction, pIrpStack->MinorFunction, pIrpStack->Control,
			pIrpStack->DeviceObject, pIrpStack->FileObject));			

	IoCompleteRequest(Irp, IO_NO_INCREMENT);	
	return STATUS_SUCCESS;
}

static NTSTATUS loop_read(IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp)
{
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
	
	KdPrint(("%s type = %d, UserBuffer = %p\n", __FUNCTION__, Irp->Type, Irp->UserBuffer));
	KdPrint(("%s[%d][%d] control[%d] DeviceObject = %p, FileObject = %p\n", __FUNCTION__,
			pIrpStack->MajorFunction, pIrpStack->MinorFunction, pIrpStack->Control,
			pIrpStack->DeviceObject, pIrpStack->FileObject));			

	if (Irp->UserBuffer)
	{
		KdPrint(("%s type = %d, UserBuffer = %s\n", __FUNCTION__, Irp->Type, Irp->UserBuffer));
		memcpy(Irp->UserBuffer, __FUNCTION__, strlen(__FUNCTION__) + 1);
	}
	IoCompleteRequest(Irp, IO_NO_INCREMENT);	
	return STATUS_SUCCESS;
}

static NTSTATUS loop_write(IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp)
{
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);	

	KdPrint(("%s type = %d, UserBuffer = %p\n", __FUNCTION__, Irp->Type, Irp->UserBuffer));
	KdPrint(("%s[%d][%d] control[%d] DeviceObject = %p, FileObject = %p\n", __FUNCTION__,
			pIrpStack->MajorFunction, pIrpStack->MinorFunction, pIrpStack->Control,
			pIrpStack->DeviceObject, pIrpStack->FileObject));			

	IoCompleteRequest(Irp, IO_NO_INCREMENT);	
	return STATUS_SUCCESS;
}


#if 0
NTSTATUS pass_through(IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp)
{
	ntfs_ext *ext;
	NTSTATUS ret = STATUS_SUCCESS;
	UCHAR *name;

	name = GetCurProcName();
	if (RtlCompareMemory(name, "notepad.exe", 11) == 11)
	{
		KdPrint(("pass_through type = %d\n", Irp->Type));		
	}
	else
	{
		KdPrint(("pass_through [%s]type = %d\n", name, Irp->Type));				
	}
	
	IoSkipCurrentIrpStackLocation(Irp);
	ext = (ntfs_ext *)(DeviceObject->DeviceExtension);
/*
	ret = IoCallDriver(ext->dev_obj, Irp);
*/
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return ret;
}
#endif

static UNICODE_STRING link_name;
static PDEVICE_OBJECT loop_obj = NULL;

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
{
	IoDeleteSymbolicLink(&link_name);
	if (loop_obj)
		IoDeleteDevice(loop_obj);
	loop_obj = NULL;
}

NTSTATUS DriverEntry (
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath	)
{
	NTSTATUS ret;
	UNICODE_STRING name;
	int i;

	pDriverObject->DriverUnload = DriverUnload;
	
/*
	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i) {
		pDriverObject->MajorFunction[i] = pass_through;
	}
*/	
	RtlInitUnicodeString(&name, L"\\FileSystem\\testloop");
//	ret = IoCreateDevice(pDriverObject, sizeof(ntfs_ext), &name, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &dev_obj);
	ret = IoCreateDevice(pDriverObject, 0, &name, /*ntfs_obj->DeviceType*/FILE_DEVICE_UNKNOWN, 0, FALSE, &loop_obj);
	if (ret != STATUS_SUCCESS) {
		KdPrint(("testloop : %s : IoCreateDevice fail[0x%x]\n", __FUNCTION__, ret));
		loop_obj = NULL;
		return STATUS_SUCCESS;	
	}

	RtlInitUnicodeString(&link_name, L"\\??\\testloop_link");
	IoDeleteSymbolicLink(&link_name);
	ret = IoCreateSymbolicLink(&link_name, &name);
	if (ret != STATUS_SUCCESS) {
		KdPrint(("testloop : %s : IoCreateSymbolicLink fail[0x%x]\n", __FUNCTION__, ret));
		return STATUS_SUCCESS;	
	}
	SetFlag(loop_obj->Flags, DO_BUFFERED_IO );
/*	
    if (FlagOn(ntfs_obj->Flags, DO_BUFFERED_IO )) {
        SetFlag(dev_obj->Flags, DO_BUFFERED_IO );
    }

    if (FlagOn(ntfs_obj->Flags, DO_DIRECT_IO )) {
        SetFlag(dev_obj->Flags, DO_DIRECT_IO );
    }

    if (FlagOn(ntfs_obj->Characteristics, FILE_DEVICE_SECURE_OPEN ) ) {
        SetFlag(dev_obj->Characteristics, FILE_DEVICE_SECURE_OPEN );
    }
*/	

	pDriverObject->MajorFunction[IRP_MJ_CREATE] = ignore;
	pDriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = ignore;
	pDriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = ignore;
	pDriverObject->MajorFunction[IRP_MJ_READ] = loop_read;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = loop_write;	
/* todo	
	pDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = sfilter_fs_ctrl;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = sfilter_close;
	pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = sfilter_cleanup;
*/
	KdPrint(("testloop : %s success\n", __FUNCTION__));	
	return STATUS_SUCCESS;
}




